﻿using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Text;

namespace AnnieSharp
{
    public class Shape : DisplayObject
    {
        public Shape()
        {
            this._instanceType = "annie.Shape";
        }

        private List<DrawCommand> _command = new List<DrawCommand>();


        public static void GetGradientColor(List<Point> points, List<string> colors)
        {
            throw new Exception("尚未实现GetGradientColor");
        }


        public static void getBitmapStyle(dynamic image)
        {
            throw new Exception("尚未实现GetGradientColor");
        }


        public static SKColor GetRGBA(string color, float alpha)
        {
            var skcolor = color.ToRGBSkColor();
            skcolor = skcolor.WithAlpha(alpha.ToAlphaByte());
            return skcolor;
        }

        private List<float> _isBitmapStroke;
        private List<float> _isBitmapFill;

        /**
         * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
         * 是否对矢量使用像素碰撞 默认开启
         * @property hitTestWidthPixel
         * @type {boolean}
         * @default true
         * @since 1.1.0
         */
        public bool HitTestWidthPixel { get; set; } = true;

        /**
         * 添加一条绘画指令,具体可以查阅Html Canvas画图方法
         * @method addDraw
         * @param {string} commandName ctx指令的方法名 如moveTo lineTo arcTo等
         * @param {Array} params
         * @public
         * @since 1.0.0
         * @return {void}
         */
        public void AddDraw(CommandName commandName, List<float> paras) {
            _UI.UD = true;
            _command.Add(new DrawCommand() {
                FillType = FillType.Vector,
                CommandName = commandName,
                Paras = paras
            });
        }

        /// <summary>
        /// 画一个带圆角的矩形
        /// </summary>
        /// <param name="x">点x值</param>
        /// <param name="y">点y值</param>
        /// <param name="w">宽</param>
        /// <param name="h">高</param>
        /// <param name="rTL">左上圆角半径</param>
        /// <param name="rTR">右上圆角半径</param>
        /// <param name="rBL">左下圆角半径</param>
        /// <param name="rBR">右上圆角半径</param>
        public void DrawRoundRect(float x,float y,float w,float h,float rTL=0,float rTR=0,float rBL=0,float rBR = 0)
        {   
            var max = (w < h ? w : h) / 2;
            float mTL = 0, mTR = 0, mBR = 0, mBL = 0;
            if (rTL < 0)
            {
                rTL *= (mTL = -1);
            }
            if (rTL > max)
            {
                rTL = max;
            }
            if (rTR < 0)
            {
                rTR *= (mTR = -1);
            }
            if (rTR > max)
            {
                rTR = max;
            }
            if (rBR < 0)
            {
                rBR *= (mBR = -1);
            }
            if (rBR > max)
            {
                rBR = max;
            }
            if (rBL < 0)
            {
                rBL *= (mBL = -1);
            }
            if (rBL > max)
            {
                rBL = max;
            }

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.MoveTo,
                Paras = new List<float>() { x + w - rTR, y }
            }) ;

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x + w + rTR * mTR, y - rTR * mTR, x + w, y + rTR, rTR }
            });


            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x + w, y + h - rBR }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x + w + rBR * mBR, y + h + rBR * mBR, x + w - rBR, y + h, rBR }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x + rBL, y + h }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x - rBL * mBL, y + h + rBL * mBL, x, y + h - rBL, rBL }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x, y + rTL }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x - rTL * mTL, y - rTL * mTL, x + rTL, y, rTL }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ClosePath,
            });
        }

        /// <summary>
        /// 绘画时移动到某一点
        /// </summary>
        /// <param name="x">x</param>
        /// <param name="y">y</param>
        public void MoveTo(float x,float y)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.MoveTo,
                Paras = new List<float>() { x, y }
            });
        }

        /// <summary>
        /// 从上一点画到某一点,如果没有设置上一点，则上一点默认为(0,0)
        /// </summary>
        /// <param name="x">x</param>
        /// <param name="y">y</param>
        public void LineTo(float x, float y)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x, y }
            });
        }

        /// <summary>
        /// 从上一点画弧到某一点,如果没有设置上一点，则上一点默认为(0,0)
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void ArcTo(float x, float y)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x, y }
            });
        }

        /// <summary>
        /// 二次贝赛尔曲线 从上一点画二次贝赛尔曲线到某一点,如果没有设置上一点，则上一占默认为(0,0)
        /// </summary>
        /// <param name="cpX">控制点X</param>
        /// <param name="cpY">控制点Y</param>
        /// <param name="x">终点X</param>
        /// <param name="y">终点Y</param>
        public void QuadraticCurveTo(float cpX,float cpY,float x, float y)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.QuadTo,
                Paras = new List<float>() { cpX, cpY, x, y }
            });
        }

        /// <summary>
        /// 上一点画三次贝赛尔曲线到某一点,如果没有设置上一点，则上一占默认为(0,0)
        /// </summary>
        /// <param name="cpX"></param>
        /// <param name="cpY"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void BezierCurveTo(float cp1X, float cp1Y, float cp2X, float cp2Y, float x, float y)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.CubicTo,
                Paras = new List<float>() { cp1X, cp1Y, cp2X, cp2Y, x, y }
            });
        }

        /// <summary>
        /// 闭合一个绘画路径
        /// </summary>
        public void ClosePath()
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ClosePath
            });
        }

        /// <summary>
        /// 画一个矩形
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        public void DrawRect(float x,float y,float w,float h)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.MoveTo,
                Paras = new List<float>() { x, y }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x + w, y }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x + w, y + h }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.LineTo,
                Paras = new List<float>() { x, y + h }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ClosePath,
            });
         
        }

        /// <summary>
        /// 画一个弧形
        /// </summary>
        /// <param name="x">起始点x</param>
        /// <param name="y">起始点y</param>
        /// <param name="radius">半径</param>
        /// <param name="start">开始角度</param>
        /// <param name="end">结束角度</param>
        public void DrawArc(float x,float y,float radius,float start,float end)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x, y, radius, start / 180 * (float)Math.PI, end / 180 * (float)Math.PI }
            });
        }

        /// <summary>
        /// 画一个圆
        /// </summary>
        /// <param name="x">圆心x</param>
        /// <param name="y">圆心y</param>
        /// <param name="radius">半径</param>
        public void DrawCircle(float x,float y,float radius)
        {
            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.ArcTo,
                Paras = new List<float>() { x, y, radius, 0, 2 * (float)Math.PI }
            });
        }

        /// <summary>
        /// 画一个椭圆
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        public void DrawEllipse(float x,float y,float w,float h)
        {
            float k = 0.5522848f;
            float ox = (w / 2) * k;
            float oy = (h / 2) * k;
            float xe = x + w;
            float ye = y + h;
            float xm = x + w / 2;
            float ym = y + h / 2;

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.MoveTo,
                Paras = new List<float>() { x, ym }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.CubicTo,
                Paras = new List<float>() { x, ym - oy, xm - ox, y, xm, y }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.CubicTo,
                Paras = new List<float>() { xm + ox, y, xe, ym - oy, xe, ym }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.CubicTo,
                Paras = new List<float>() { xe, ym + oy, xm + ox, ye, xm, ye }
            });

            _command.Add(new DrawCommand()
            {
                FillType = FillType.Vector,
                CommandName = CommandName.CubicTo,
                Paras = new List<float>() { xm - ox, ye, x, ym + oy, x, ym }
            });
        }

        /// <summary>
        /// 清除之前绘制的内容
        /// </summary>
        public void Clear()  {
            _command.RemoveAll(x=>true);
            _UI.UD = true;
            if (Texture != null)
            {
                //Texture.Width = 0;
                //Texture.Height = 0;
            }
            OffsetX = 0;
            OffsetY = 0;
            _bounds.Width = 0;
            _bounds.Height = 0;
        }



        public override void Destroy()
        {
            base.Destroy();
            _command = null;
        }

    }



public class DrawCommand
    {
        /// <summary>
        /// 绘图类型
        /// </summary>
        public FillType FillType { get; set; }
        /// <summary>
        /// 绘图指令名称
        /// </summary>
        public CommandName CommandName { get; set; }
        /// <summary>
        /// 绘图数值参数
        /// </summary>
        public List<float> Paras { get; set; } = new List<float>();
        /// <summary>
        /// 对象类型参数
        /// </summary>
        private object Para { get; set; }
        ///// <summary>
        ///// 其他绘制参数
        ///// </summary>
        //public List<string> ParasExtension { get; set; }
    }

    /// <summary>
    /// 指令名
    /// </summary>
    public enum CommandName
    {
        /// <summary>
        /// 开始新的轮廓
        /// </summary>
        MoveTo,
        /// <summary>
        /// 向路径添加一条直线
        /// </summary>
        LineTo,
        /// <summary>
        /// 添加一段弧线，这是圆或椭圆圆周上的线条
        /// </summary>
        ArcTo,
        /// <summary>
        /// 添加的三次方贝塞尔样条
        /// </summary>
        CubicTo,
        /// <summary>
        /// 添加的二次贝塞尔样条
        /// </summary>
        QuadTo,
        /// <summary>
        /// 添加的合理二次贝塞尔样条，可以准确地呈现圆锥部分 （椭圆、 条抛物线合理组合和 hyperbolas） 的
        /// </summary>
        ConicTo,
        /// <summary>
        /// 闭合路径
        /// </summary>
        ClosePath
    } 

    /// <summary>
    /// 填充类型
    /// </summary>
    public enum FillType
    {
        /// <summary>
        /// 不填充
        /// </summary>
        Empty = 0,
        /// <summary>
        /// 矢量填充
        /// </summary>
        Vector = 1,
        /// <summary>
        /// 位图填充
        /// </summary>
        Bitmap =2

    }
}
